package com.whtq.front.common.util;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.Socket;
import java.util.Arrays;

/**
 * Created by
 *
 * @author wmi
 * @date 2019/10/23
 * @description
 */
public class DefaultSocket {
    private static final Logger logger = LoggerFactory.getLogger(DefaultSocket.class);
    private String biz;
    private String ip;
    private int port;
    private int timeoutSecends;
    private int timeoutSecendsDefault = 30;
    private String charsetName = "UTF-8";
    private Socket socket = null;
    private OutputStream outputStream = null;
    private InputStream inputStream = null;

    public DefaultSocket(String ip, int port, int timeoutSecends, String charsetName, String biz){
        if(timeoutSecends<1){
            logger.warn("invalid timeoutSecends. use default :{}", timeoutSecendsDefault);
            this.timeoutSecends = timeoutSecendsDefault;
        }else{
            this.timeoutSecends = timeoutSecends;
        }
        this.ip = ip;
        this.port = port;
        this.charsetName = charsetName;
        this.biz = biz;
    }

    public DefaultSocket(String ip, int port, String charsetName, String biz){
        this.ip = ip;
        this.port = port;
        this.charsetName = charsetName;
        this.timeoutSecends = timeoutSecendsDefault;
        this.biz = biz;
    }

    public DefaultSocket(String ip, int port, String biz){
        this.ip = ip;
        this.port = port;
        this.timeoutSecends = timeoutSecendsDefault;
        this.biz = biz;
    }

    public void send(String msg){
        logger.debug("biz:{}, send to {}:{} ", biz, ip, port);
        try {
            socket = new Socket(ip, port);
            socket.setSoTimeout(timeoutSecends*1000);
            outputStream = socket.getOutputStream();
            inputStream = socket.getInputStream();
            outputStream.write(msg.getBytes(charsetName));
            outputStream.flush();
        } catch (Exception e) {
            logger.error("", e);
            close();
        }
    }

    private void close(){
        if(outputStream!=null){
            try {
                outputStream.close();
            } catch (IOException e) {
                logger.error("", e);
            }
        }
        if(inputStream!=null){
            try {
                inputStream.close();
            } catch (IOException e) {
                logger.error("", e);
            }
        }
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                logger.error("", e);
            }
        }
    }

    public String sendMsgAndReadByLine(String msg) {
        BufferedReader br = null;
        try {
            send(msg);
            br = new BufferedReader(new InputStreamReader(
                    inputStream, charsetName));
            String ret = br.readLine();
            logger.debug("receive: {}", ret);
            return ret;
        } catch (Exception e) {
            logger.error("", e);
        } finally {
            close();
            if(br!=null){
                try {
                    br.close();
                } catch (IOException e) {
                    logger.error("", e);
                }
            }
        }
        return null;
    }

    public String sendMsgAndReadByChar(String msg) {
        InputStreamReader is = null;
        try {
            send(msg);
            is = new InputStreamReader(
                    socket.getInputStream(), charsetName);
            StringBuffer stringBuffer = new StringBuffer();
            int temp;
            while ((temp=is.read())!=-1){
                stringBuffer.append((char)temp);
            }
            String ret = stringBuffer.toString();
            logger.debug("biz:{},receive: {}", biz, ret);
            return ret;
        } catch (Exception e) {
            logger.error("", e);
        } finally {
            close();
            if(is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    logger.error("", e);
                }
            }
        }
        return null;
    }

    public String sendMsgAndReadByMessageLengthHex(String msg, int messageLengthByteNum) {
        return sendMsgAndReadByMessageLength(msg, messageLengthByteNum, HeadTypeEnum.Hex);
    }

    public String sendMsgAndReadByMessageLengthDecimal(String msg, int messageLengthByteNum) {
        return sendMsgAndReadByMessageLength(msg, messageLengthByteNum, HeadTypeEnum.Decimal);
    }
    

    private String sendMsgAndReadByMessageLength(String msg, int messageLengthByteNum, HeadTypeEnum headType) {
        try {
            send(msg);
            byte[] head = new byte[messageLengthByteNum];
            int packetLength = -1;
            packetLength = inputStream.read(head);
            if (packetLength != head.length) {
                logger.error("读取错误：packetLength={}", packetLength);
                throw new IOException("读取包长度错误!");
            }
            logger.debug(Arrays.toString(head));
            packetLength = byte2short(head, headType);
            logger.debug("packetLength={}", packetLength);
            byte[] packet = new byte[packetLength];
            inputStream.read(packet);
            String ret = new String(packet, charsetName);
            logger.debug("receive: {}", ret);
            return ret;
        } catch (Exception e) {
            logger.error("", e);
        } finally {
            close();
        }
        return null;
    }

    private int byte2short(byte[] b, HeadTypeEnum headType) {
    	int s = 0;
    	switch(headType){
	    	case Decimal:
	    		s = Integer.valueOf(new String(b));
	    		break;
	    	case Hex:
	    		s = (((b[0] & 0xff) << 8) | (b[1] & 0xff));
	    		break;
    	}
    	return s;
    }
    
    public enum HeadTypeEnum {
        Decimal,
        Hex;
    }

}
